package main

import (
	"global/libs/ws"
	"time"
	"encoding/json"
	"github.com/ngaut/log"
	"global/constants"
	"global/core"
	"global/libs/structs"
	"github.com/shopspring/decimal"
	"global/util"
)

type Exchange struct {
	Handler  		*Handler
	exit 			chan interface{}

	req 			*ws.ExchangeListRequest

	limit 			int

	intervalC 		*time.Ticker
}

func (h *Exchange) ReadWriteMessage(handler *Handler, message ws.RequestMessage) error {
	h.Handler = handler
	h.handleRequest(message)
	return nil
}

func (h *Exchange) handleRequest(message ws.RequestMessage) {
	var req ws.ExchangeListRequest
	err := json.Unmarshal([]byte(message.Message), &req)
	if err != nil {
		log.Errorf("Error: %s", err)
	}

	if req.Direction != constants.SortTypeAsc && req.Direction != constants.SortTypeDesc {
		h.Handler.response <- ws.ErrorMsg(ws.ErrParameter, constants.RequestExchangeList)
		return
	}
	if req.Page <= 0 { req.Page = 1 }

	h.limit = req.Page * constants.PageSize

	h.req = &req
	h.getResponse()
}

func (h *Exchange) getResponse()  {
	if h.req == nil {
		return
	}

	conn := h.Handler.ctx.GetBaseRedis().Get()
	defer conn.Close()

	rate, err := core.GetCnyRateByCoin(conn, "usd")
	if err != nil {
		log.Errorf("Error: %s", err)
		return
	}

	rateDecimal, _ := decimal.NewFromString(rate)

	exchanges, err := core.GetExchangeWithSort(conn, h.req.Direction, h.limit)
	if err != nil {
		log.Errorf("Error: %s", err)
		return
	}

	// get meta data
	metas, err := core.GetAnalysisedExchangeMetaDataMulti(conn, exchanges)
	if err != nil {
		log.Errorf("Error: %s", err)
		return
	}

	// get ticker data
	tickers, err := core.GetAnalysisExchangeAmount24hDataMulti(conn, exchanges)
	if err != nil {
		log.Errorf("Error: %s", err)
		return
	}

	tickerExchangeMaps := make(map[string]*structs.ExchangeTicker)
	for _, v := range tickers {
		tickerExchangeMaps[v.Exchange] = v
	}

	data := make([]*ws.ExchangeListResponse, 0)
	for _, v := range metas {
		t, ok := tickerExchangeMaps[v.Slug]
		if !ok { continue }

		usd, _ := decimal.NewFromString(t.AmountUsd)

		data = append(data, &ws.ExchangeListResponse{
			Slug: 		v.Slug,
			NameCn: 	v.NameCn,
			NameEn: 	v.NameEn,
			Logo: 		util.ImageUrl(h.Handler.ctx.GetImgUrl(), v.Logo),
			AmountUsd:	t.AmountUsd,
			AmountCny: 	usd.Mul(rateDecimal).StringFixedBank(8),
			NumCoins: 	t.CountCoins,
			NumMarkets: t.CountMarkets,
			NumPairs: 	t.CountPairs,
		})
	}

	h.Handler.response <- ws.WsResponse(data, constants.RequestCoinExchange)
}

func (h *Exchange) Init()  {
	h.req = nil
	h.exit = make(chan interface{})
	h.intervalC = time.NewTicker(2 * time.Second)
	go func() {
		for {
			select {
			case <-h.exit:
				h.intervalC.Stop()
				return
			case <-h.intervalC.C:
				h.getResponse()
			}
		}
	}()
}

func (h *Exchange) Clear() {
	h.exit <- true
}